package aor2.cpu.blockinterrupt;

import aor2.components.FlipFlopException;
import aor2.components.FlipFlopRS;
import aor2.components.Restorable;
import aor2.components.Signal;
import aor2.cpu.blockcontrol.ConditionSignalSet;
import aor2.cpu.blockcontrol.ControlSignalSet;
import aor2.cpu.blockoperation.Psw;

public class ExternInterruptBoard implements Restorable {
	FlipFlopRS ffirr1, ffirr2, ffirr3, ffinm, ffprirr1, ffprirr2, ffprirr3,
			ffprinm;
	Signal clirr, ldprcod, clinm, prinm, qirr1, qirr2, qirr3, qinm, qprirr1,
			qprirr2, qprirr3, sprirr1, sprirr2, sprirr3, sprinm, rprirr1,
			rprirr2, rprirr3;
	Signal notintr1, notintr2, notintr3, inm, intr1, intr2, intr3;
	Psw psw;
	boolean clkFstPhase;

	ExternInterruptBoard() {
		ControlSignalSet css = ControlSignalSet.getInstance();
		InterruptSignalSet iss = InterruptSignalSet.getInstance();

		clirr = css.get("clprirr");
		ldprcod = css.get("ldprcod");

		clinm = css.get("clprinm");
		inm = iss.get("inm");
		qinm = iss.get("PINM");
		sprinm = iss.get("STINM");
		prinm = ConditionSignalSet.getInstance().get("PRINM");

		qirr1 = iss.get("SINTR1");
		qirr2 = iss.get("SINTR2");
		qirr3 = iss.get("SINTR3");

		qprirr1 = iss.get("PRIRR1");
		qprirr2 = iss.get("PRIRR2");
		qprirr3 = iss.get("PRIRR2");
		sprirr1 = iss.get("STINTR1");
		sprirr2 = iss.get("STINTR2");
		sprirr3 = iss.get("STINTR3");
		rprirr1 = iss.get("CLRINTR1");
		rprirr2 = iss.get("CLRINTR2");
		rprirr3 = iss.get("CLRINTR3");

		notintr1 = iss.get("notintr1");
		notintr2 = iss.get("notintr2");
		notintr3 = iss.get("notintr3");

		intr1 = new Signal(false);
		intr2 = new Signal(false);
		intr3 = new Signal(false);

		clkFstPhase = true;

		ffirr1 = new FlipFlopRS(rprirr1, intr1, qirr1);
		ffirr2 = new FlipFlopRS(rprirr2, intr2, qirr2);
		ffirr3 = new FlipFlopRS(rprirr3, intr3, qirr3);
		ffinm = new FlipFlopRS(clinm, inm, qinm);

		ffprirr1 = new FlipFlopRS(rprirr1, sprirr1, qprirr1);
		ffprirr2 = new FlipFlopRS(rprirr2, sprirr2, qprirr2);
		ffprirr3 = new FlipFlopRS(rprirr3, sprirr3, qprirr3);
		ffprinm = new FlipFlopRS(clinm, sprinm, prinm);

		psw = Psw.getInstance();
	}

	public void next() {
		intr1.setActive(!notintr1.isActive());
		intr2.setActive(!notintr2.isActive());
		intr3.setActive(!notintr3.isActive());
		if (clkFstPhase) {
			rprirr1.setActive(false);
			rprirr2.setActive(false);
			rprirr3.setActive(false);
			if (clirr.isActive()) {
				if (psw.bitL0() && psw.bitL1())
					rprirr3.setActive(true);
				if (psw.bitL1())
					rprirr2.setActive(true);
				if (psw.bitL0())
					rprirr1.setActive(true);
			}
			sprirr1.setActive(false);
			sprirr2.setActive(false);
			sprirr3.setActive(false);

			try {
				ffirr1.out();
				ffirr2.out();
				ffirr3.out();
				ffinm.out();
				ffprirr1.out();
				ffprirr2.out();
				ffprirr3.out();
				ffprinm.out();
			} catch (FlipFlopException e) {
				e.printStackTrace();
			}

			if (ldprcod.isActive()) {
				if (qirr1.isActive()) {
					sprirr1.setActive(true);
				}
				if (qirr2.isActive()) {
					sprirr2.setActive(true);
				}
				if (qirr3.isActive()) {
					sprirr3.setActive(true);
				}
			}

		} else {
			try {
				ffirr1.in();
				ffirr2.in();
				ffirr3.in();
				ffinm.in();
				ffprirr1.in();
				ffprirr2.in();
				ffprirr3.in();
				ffprinm.in();
			} catch (FlipFlopException e) {
				e.printStackTrace();
			}
		}
		clkFstPhase = !clkFstPhase;
	}

	public Signal getQirr1() {
		return qirr1;
	}

	public void setQirr1(Signal qirr1) {
		this.qirr1 = qirr1;
	}

	public Signal getQirr2() {
		return qirr2;
	}

	public void setQirr2(Signal qirr2) {
		this.qirr2 = qirr2;
	}

	public Signal getQirr3() {
		return qirr3;
	}

	public void setQirr3(Signal qirr3) {
		this.qirr3 = qirr3;
	}

	public Signal getQinm() {
		return qinm;
	}

	public void setQinm(Signal qinm) {
		this.qinm = qinm;
	}

	public Signal getSprirr1() {
		return sprirr1;
	}

	public void setSprirr1(Signal sprirr1) {
		this.sprirr1 = sprirr1;
	}

	public Signal getSprirr2() {
		return sprirr2;
	}

	public void setSprirr2(Signal sprirr2) {
		this.sprirr2 = sprirr2;
	}

	public Signal getSprirr3() {
		return sprirr3;
	}

	public void setSprirr3(Signal sprirr3) {
		this.sprirr3 = sprirr3;
	}

	public Signal getSprinm() {
		return sprinm;
	}

	public void setSprinm(Signal sprinm) {
		this.sprinm = sprinm;
	}

	public Signal getRprirr1() {
		return rprirr1;
	}

	public void setRprirr1(Signal rprirr1) {
		this.rprirr1 = rprirr1;
	}

	public Signal getRprirr2() {
		return rprirr2;
	}

	public void setRprirr2(Signal rprirr2) {
		this.rprirr2 = rprirr2;
	}

	public Signal getRprirr3() {
		return rprirr3;
	}

	public void setRprirr3(Signal rprirr3) {
		this.rprirr3 = rprirr3;
	}

	public Signal getNotintr1() {
		return notintr1;
	}

	public void setNotintr1(Signal notintr1) {
		this.notintr1 = notintr1;
	}

	public Signal getNotintr2() {
		return notintr2;
	}

	public void setNotintr2(Signal notintr2) {
		this.notintr2 = notintr2;
	}

	public Signal getNotintr3() {
		return notintr3;
	}

	public void setNotintr3(Signal notintr3) {
		this.notintr3 = notintr3;
	}

	public Signal getInm() {
		return inm;
	}

	public void setInm(Signal inm) {
		this.inm = inm;
	}

	public Signal getIntr1() {
		return intr1;
	}

	public void setIntr1(Signal intr1) {
		this.intr1 = intr1;
	}

	public Signal getIntr2() {
		return intr2;
	}

	public void setIntr2(Signal intr2) {
		this.intr2 = intr2;
	}

	public Signal getIntr3() {
		return intr3;
	}

	public void setIntr3(Signal intr3) {
		this.intr3 = intr3;
	}

	public Signal getQprirr1() {
		return qprirr1;
	}

	public Signal getQprirr2() {
		return qprirr2;
	}

	public Signal getQprirr3() {
		return qprirr3;
	}

	@Override
	public void restore(String restorePoint) {
		String trim = restorePoint.replace(beginTag(), "");
		trim = trim.replace(endTag(), "");
		trim = trim.trim();
		String[] states = trim.split(" ");
		int i = 0;

		intr1.clearHistory();
		intr2.clearHistory();
		intr3.clearHistory();

		intr1.setActive(Boolean.parseBoolean(states[i++]));
		intr2.setActive(Boolean.parseBoolean(states[i++]));
		intr3.setActive(Boolean.parseBoolean(states[i++]));

		clkFstPhase = Boolean.parseBoolean(states[i++]);
	}

	@Override
	public String createRestorePoint() {
		return beginTag() + "\n\t" +

		intr1.isActive() + " " + intr2.isActive() + " " + intr3.isActive()
				+ " " +

				clkFstPhase + "\n" + endTag();
	}

	@Override
	public String beginTag() {
		return "<EIB>";
	}

	@Override
	public String endTag() {
		return "</EIB>";
	}

	public void previousClk() {
		clkFstPhase = true;
		intr1.previousClk();
		intr2.previousClk();
		intr3.previousClk();

		ffirr1.previousClk();
		ffirr2.previousClk();
		ffirr3.previousClk();
		ffinm.previousClk();

		ffprirr1.previousClk();
		ffprirr2.previousClk();
		ffprirr3.previousClk();
		ffprinm.previousClk();
	}

}
